package ServerUDP;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

public class ServerUDP {
    private static Charset charset=Charset.forName("utf8");
    public static void main(String[] args) throws IOException {
        int max=3;
        int port=888;
        DatagramChannel channel=DatagramChannel.open();//0用于延迟，1、2、3用于吞吐量
        Selector selector=Selector.open();
        channel.configureBlocking(false);//指定为非阻塞模式
        channel.socket().bind(new InetSocketAddress(port));
        channel.register(selector, SelectionKey.OP_READ);//读模式

        DatagramChannel[] channels=new DatagramChannel[max];
        Selector[] selectors=new Selector[max];
        for(int i=0;i<max;++i){
            selectors[i]=Selector.open();
            channels[i]=DatagramChannel.open();//0用于延迟，1、2、3用于吞吐量
            channels[i].configureBlocking(false);//指定为非阻塞模式
            channels[i].socket().bind(new InetSocketAddress(port+1+i));
            channels[i].register(selectors[i], SelectionKey.OP_READ);//读模式
        }


        ByteBuffer writebuffer=ByteBuffer.allocate(1024);
        ByteBuffer readBuffer = ByteBuffer.allocate(1024);//读缓冲

        System.out.println("启动服务器....");
        while (true){
            //没有事件发生
            if(selector.select()<1){
                continue;
            }
            //获取发生的事件
            Set<SelectionKey> keys=selector.selectedKeys();
            Iterator<SelectionKey> it=keys.iterator();//用于检测事件发生
            while(it.hasNext()){
                //获取事件，移除当前事件
                SelectionKey key=it.next();
                it.remove();

                if(key.isReadable()){
                    DatagramChannel datagramChannel=(DatagramChannel) key.channel();
                    readBuffer.clear();
                    SocketAddress sa=datagramChannel.receive(readBuffer);
                    readBuffer.flip();
                    //如果接收到的是begin，说明是测延迟的连接，给它返回一个receive就行
                    if(charset.decode(readBuffer).toString().equals("begin")) {
                        writebuffer.put("receive".getBytes());
                        writebuffer.flip();
                        channel.send(writebuffer, sa);
                        writebuffer.clear();
                        System.out.println("receive");
                        ThroughputUDP[] throughputUDP=new ThroughputUDP[max];
                        for(int i=0;i<max;++i){
                            System.out.println("开始启动新线程");
                            throughputUDP[i] = new ThroughputUDP(channels[i],selectors[i]);
                            throughputUDP[i].start();
                        }
                        for(int i=0;i<max;++i){
                            //主线程其他工作完毕,等待子线程的结束, 调用join系列的方法即可(可以设置超时时间)
                            try {
                                throughputUDP[i].join();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }

        }
    }
}

